#ifndef MAPSDISK_H_
#define MAPSDISK_H_


#include <iostream>
#include <map>
#include <string>
#include <sstream>

#include <fstream>

#include "WellSizedVector.h"
#include "PositionVector.h"
#include "Aurelio.h"

using namespace std;

class MapsDisk {
public:
	
	MapsDisk(){
		miniMapsInfo.miniMapCouter = 0;
	};
	~MapsDisk(){};
	
	string intToStr(unsigned long long num){
		stringstream sTemp;
		sTemp << hex << num << dec;
		return sTemp.str();
	}
	
	
	void writeMiniMap(map<unsigned long long, WellSizedVector> & wordDictionary){
		
		string file_name = "/work/miniMaps/miniMapsFile_";
		file_name += intToStr(miniMapsInfo.miniMapCouter);
		
		ofstream miniMapsFile(file_name.c_str());
		miniMapsInfo.miniMapCouter++;
	
		map<unsigned long long, WellSizedVector>::iterator it;
		
//		for (it = myFriendAurelio.wordDictionary.begin(); it != myFriendAurelio.wordDictionary.end(); it++) {
//			cout << "Palavra Hash: " << it->first << endl;
//			cout << "Quantidade: " << (it->second).getVectorSize() << endl;
//			cout << "Presente nos documentos: " << (it->second).listDocs() << endl;
//			cout << endl;
//		}	
		string infoLine;
//		cout << "wordDictionary: " << endl;
//		cout << "Size: " << myFriendAurelio.wordDictionary.size() << endl;
		for (it = wordDictionary.begin(); it != wordDictionary.end(); it++) {
			// unsigned long long
//			cout << "\t ID: " << it->first << endl;
			infoLine += intToStr( it->first ) + ":";
			// WellSizedVector
//			cout << "\t vectorIndex: " << (it->second).vectorIndex << endl;
			infoLine += intToStr(( it->second).vectorIndex ) + ":";
//			cout << "\t documents Size: " << (it->second).documents.size() << endl;
			infoLine += intToStr( (it->second).documents.size() ) + ":";
			
			// PositionVector
			vector<PositionVector>::iterator itt;
			for(itt = (it->second).documents.begin(); itt != (it->second).documents.end(); itt++){
//				cout << "\t\t PositionVector id: " << itt->id << endl;
				infoLine += intToStr( itt->id ) + ":";
//				cout << "\t\t PositionVector firstOccurrence: " << itt->firstOccurrence << endl;
				infoLine += intToStr( itt->firstOccurrence ) + ":";
//				cout << "\t\t position Size(): " << itt->positions.size() << endl;
				infoLine += intToStr( itt->positions.size() ) + ":";
				
				vector<unsigned short>::iterator ittt;
				for(ittt = itt->positions.begin(); ittt != itt->positions.end(); ittt++){
//					cout << "\t\t\t unsigned short: " << *ittt << endl;
					infoLine += intToStr( *ittt ) + ":";
				}
			}
//			cout << "String Line: " << infoLine << endl;
			miniMapsFile << infoLine << endl;
			infoLine.clear();
		}		
	}
	
	void readMiniMap(map<unsigned long long, WellSizedVector> & wordDictionary){
		
		string file_name = "miniMapsFile_";
		if(miniMapsInfo.miniMapCouter == 0) return;
		file_name += intToStr(miniMapsInfo.miniMapCouter - 1);
		ifstream miniMapsFile(file_name.c_str());
		cout << "Recuperando minimapa:  " << file_name << endl;
		string infoLine;
		
		while(true){
			miniMapsFile >> infoLine;
			if( !miniMapsFile.eof() ){
				
				cout << "Item: " << infoLine << endl;			
				//	 ID: 18046255357
				//	 vectorIndex: 1
				//	 documents Size: 1
				//		 PositionVector id: 4
				//       firstOccurrence
				//		 position Size(): 1
				//			 unsigned short: 7
				
				unsigned long long ID = 0;
				unsigned long vectorIndex = 0;
				unsigned long documentsSize = 0;
				unsigned long PositionVectorId = 0;
				unsigned long firstOccurrence = 0;
				unsigned long positionSize = 0;
				unsigned long unsignedShort = 0;

				int posA, posB;
				int elementoCont;
				
				elementoCont = 0;
				posA = 0;
				
				PositionVector tempPos;
				WellSizedVector tempWSV;
				
				while(posA < infoLine.size()){
					posB = infoLine.find_first_of(":",posA);
					if(posB == string::npos) break;
					
					if(elementoCont == 0){
						stringstream(infoLine.substr(posA, posB-posA)) >> ID;
					}
					else if(elementoCont == 1){
						stringstream(infoLine.substr(posA, posB-posA)) >> vectorIndex;
						tempWSV.vectorIndex = vectorIndex;
						tempWSV.initializeVector();
					}
					else if(elementoCont == 2){
						stringstream(infoLine.substr(posA, posB-posA)) >> documentsSize;
					}
					else if(elementoCont == 3){
						stringstream(infoLine.substr(posA, posB-posA)) >> PositionVectorId;
						tempPos.id = PositionVectorId;
					}
					else if(elementoCont == 4){ //novo
						stringstream(infoLine.substr(posA, posB-posA)) >> firstOccurrence;
						tempPos.firstOccurrence = firstOccurrence;
					}
					else if(elementoCont == 5){
						stringstream(infoLine.substr(posA, posB-posA)) >> positionSize;
						tempPos.initializeVector(positionSize);
					}
					else if(elementoCont < 6 +  positionSize){  //pena numShorts
						stringstream(infoLine.substr(posA, posB-posA)) >> unsignedShort;
						tempPos.insertPosition(unsignedShort);
					}
					else {  // pega mais info dos vetores retornando para PositionVectorId
						elementoCont = 3;
						
						tempWSV.documents.push_back(tempPos);
						
						continue;
					}
//					cout << "Elemento: " << elementoCont << " : "<< infoLine.substr(posA, posB-posA) << endl;
					posA = posB+1;
					elementoCont++;
				}

				wordDictionary[ID] = tempWSV;
				
				cout << "ID: " << ID << endl;
				cout << "\tvectorIndex: " << vectorIndex << endl;
				cout << "\tdocumentsSize: " << documentsSize << endl;
				cout << "\t\tPositionVectorId: " << PositionVectorId << endl;
				cout << "\t\tpositionSize: " << positionSize << endl; 
				cout << "\t\t\tunsignedShort: " << unsignedShort << endl; 
				
			}else break;
		}
	}
			
private:
	struct _miniMapsInfo{
		unsigned int miniMapCouter;
	} miniMapsInfo;
};


#endif /*MAPSDISK_H_*/
